package com.green.common.util;

import java.io.IOException;
import java.security.Key;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class PBEUtils {
    /** 
     * 支持以下任意一种算法 
     *  
     * <pre> 
     * PBEWithMD5AndDES  
     * PBEWithMD5AndTripleDES  
     * PBEWithSHA1AndDESede 
     * PBEWithSHA1AndRC2_40 
     * </pre> 
     */  
    public static final String ALGORITHM = "PBEWITHMD5andDES";  
  
    /** 
     * 盐初始化 
     *  
     * @return 
     * @throws Exception 
     */  
    public static byte[] initSalt() {  
        byte[] salt = new byte[8];  
        Random random = new Random();  
        random.nextBytes(salt);  
        return salt;  
    }  
  
    /** 
     * 转换密钥<br> 
     *  
     * @param password 
     * @return 
     * @throws Exception 
     */  
    private static Key toKey(String password) {  
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());  
		try {
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
			SecretKey secretKey = keyFactory.generateSecret(keySpec);  
			return secretKey;  
		} catch (Exception e) {
			throw new RuntimeException(e);
		}  
    }  
  
    /** 
     * 加密 
     *  
     * @param data 数据 
     * @param password 密码 
     * @param salt 盐 
     * @return 
     * @throws Exception 
     */  
    public static byte[] encrypt(byte[] data, String password, byte[] salt) {  
        Key key = toKey(password);  
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);  
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);  
			
			return cipher.doFinal(data);  
		} catch (Exception e) {
			throw new RuntimeException(e);
		}  
  
    }  
  
    /** 
     * 解密 
     *  
     * @param data 数据 
     * @param password 密码 
     * @param salt 盐 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decrypt(byte[] data, String password, byte[] salt) {  
        Key key = toKey(password);  
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);  
		try {
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);  
			
			return cipher.doFinal(data);  
		} catch (Exception e) {
			throw new RuntimeException(e);
		}  
  
    }  
    
    /** 
     * BASE64解密 
     *  
     * @param value 
     * @return 
     * @throws Exception 
     */  
    public static byte[] decryptBASE64(String value)  {  
        try {
			return (new BASE64Decoder()).decodeBuffer(value);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}  
    }  
  
    /** 
     * BASE64加密 
     *  
     * @param value 
     * @return 
     * @throws Exception 
     */  
    public static String encryptBASE64(byte[] value)  {  
        return (new BASE64Encoder()).encodeBuffer(value);  
    }  
  
    
    public static void main(String[] args) {
        String inputStr = "13266750500";  
        System.err.println("原文: " + inputStr);  
        byte[] input = inputStr.getBytes();  
  
        String pwd = "efg";  
        System.err.println("密码: " + pwd);  
  
        byte[] salt = initSalt();  
  
        byte[] data = encrypt(input, pwd, salt);  
  
        System.err.println("加密后: " + encryptBASE64(data));  
  
        byte[] output = decrypt(data, pwd, salt);  
        String outputStr = new String(output);  
  
        System.err.println("解密后: " + outputStr);  
  
	}
}
